﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;

namespace Triples {
    public class PositionPanel : Panel {//: AnimatablePanel { //AnimatablePanel { //AnimatedPanels.AnimatedPanel { //

        public static readonly DependencyProperty PositionProperty = 
            DependencyProperty.RegisterAttached("Position", typeof(int?), 
            typeof(PositionPanel), new PropertyMetadata (null, OnPositionChanged));


        public int Columns {
            get;
            set;
        }

        public int Rows {
            get;
            set;
        }

        public double Ratio {
            get;
            set;
        }

        private ScrollViewer _ScrollViewer;

        public ScrollViewer ScrollViewer {
            get { return _ScrollViewer ?? (_ScrollViewer = Utilities.FindAncestor<ScrollViewer>(this) as ScrollViewer); }
        }


        private static void OnPositionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) {
            if (sender is UIElement) {
                (sender as UIElement).InvalidateArrange ();
            }
        }

        protected override Size MeasureOverride(Size availableSize) {
            double width = availableSize.Width / Columns;
            double height = availableSize.Height;

            double desiredHeight = 0;
            double desiredWidth = 0;

            int? highestPos = Children.Select(child => GetPosition(child)).Max();
            double?[] heights = new double?[(highestPos ?? 0) + 1];

            foreach (UIElement child in Children) {
                int? pos = GetPosition(child);

                child.Measure(new Size(width, height));
                if (pos.HasValue) heights [pos.Value] = child.DesiredSize.Height;
            }

            for (int i = 0; i < heights.Length; i+=Columns) {
                double rowHeight = 0;

                for (int j = 0; j < Columns && i + j < heights.Length; j++) {
                    if (heights[i + j].HasValue) rowHeight = Math.Max(heights[i + j].Value, rowHeight);
                }

                desiredHeight += rowHeight;
            }

            desiredWidth = Columns * width;
            
            Size desiredSize = new Size(desiredWidth, desiredHeight);
            
            base.MeasureOverride(availableSize);
            return desiredSize;
        }


        protected override Size ArrangeOverride(Size finalSize) {
            double width = finalSize.Width / Columns;

            double desiredHeight = 0;
            double desiredWidth = 0;

            int? highestPos = Children.Select<UIElement, int?>(child => GetPosition(child)).Max();

            double?[] itemHeights = new double?[(highestPos ?? 0) + 1];
            double[] rowHeights = new double[((highestPos ?? 0) / Columns) + 1];
            
            foreach (UIElement child in Children) {
                int? pos = GetPosition(child);
                if (pos.HasValue) itemHeights[pos.Value] = child.DesiredSize.Height;
            }

            for (int i = 0, k=0; k < rowHeights.Length && i <itemHeights.Length; i += Columns, k++) {
                double rowHeight = 0;

                for (int j = 0; j < Columns && i + j < itemHeights.Length; j++) {
                    if (itemHeights[i + j].HasValue) rowHeight = Math.Max(itemHeights[i + j].Value, rowHeight);
                }

                rowHeights [k] = rowHeight;
            }


            foreach (UIElement child in Children) {
                int? pos = GetPosition(child);

                if (pos.HasValue) {
                    int row = (pos.Value % Columns);
                    int col = (pos.Value / Columns);
                    double x = row * width;
                    double y = rowHeights.ToList<double>().GetRange(0, col).Sum();
                    child.Arrange(new Rect (x, y, width, rowHeights[col]));
                }
            }

            desiredHeight = rowHeights.Sum();
            desiredWidth = Columns * width;
            Size desiredSize = new Size(desiredWidth, desiredHeight);

            base.ArrangeOverride(finalSize);
            return desiredSize;
        }


        public static void SetPosition(UIElement element, int? value) {
            element.SetValue(PositionProperty, value);
        }


        public static int? GetPosition(UIElement element) {
            return (int?)element.GetValue(PositionProperty);
        }
    }
}
